/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tnviet.proj.jna;

import java.util.logging.Level;
import tnviet.proj.jna.meter.JNMeterPanel;
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.SplashScreen;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.EventObject;
import java.util.Locale;
import java.util.Properties;
import java.util.logging.Logger;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.jdesktop.animation.timing.Animator;
import org.jdesktop.animation.timing.interpolation.PropertySetter;
import org.jdesktop.application.Application;
import tnviet.proj.jna.utilities.ResourceManager;
import tnviet.proj.jna.utilities.Utilities;
import org.jdesktop.application.Application.ExitListener;
import org.jdesktop.application.ApplicationContext;
import org.jvnet.substance.SubstanceLookAndFeel;
import org.pushingpixels.trident.Timeline;
import org.pushingpixels.trident.Timeline.TimelineState;
import org.pushingpixels.trident.callback.TimelineCallbackAdapter;
import tnviet.proj.jna.bandwidth.FilterTableFrame;
import tnviet.proj.jna.dialog.ColorRulesDialog;
import tnviet.proj.jna.report.ReportPane;
import tnviet.proj.jna.utilities.JXTrayIcon;

/**
 *
 * @author Administrator
 */
public class Program extends Application{


    static final Logger logger = Logger.getLogger(Program.class.getName());

    public static JNMainFrame mainFrame;
    public static JNMeterPanel meterPane;
    public static FilterTableFrame filterTableFrame;
    public static JDialog reportDialog;
    public static String title;
    public static Locale locale;
    public static Properties JNProperty;
    public static boolean isCaptureFrameActived = false;
    public static final JPopupMenu trayMenu = new JPopupMenu();
    public static JCheckBoxMenuItem showItem;
    public static Connection connection;
    public JNCaptor jNCaptor;

    Boolean isShowMeter = null;
    Boolean isDefaultDecorated = null;
    Boolean captureFullscreen = null;

    String lookAndFeel;
    ApplicationContext ctxt = getContext();
    static {
        loadProperty();
        // Property must be set *early* due to Apple Bug#3909714
        if (System.getProperty("os.name").equals("Mac OS X")) {
            System.setProperty("apple.laf.useScreenMenuBar", "true");
        }

        // temporary workaround for problem with Nimbus classname
        UIManager.LookAndFeelInfo lafInfo[] = UIManager.getInstalledLookAndFeels();
        for(int i = 0; i < lafInfo.length; i++) {
            if (lafInfo[i].getName().equals("Nimbus")) {
                lafInfo[i] = new UIManager.LookAndFeelInfo("Nimbus",
                        "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                break;
            }
        }
        UIManager.setInstalledLookAndFeels(lafInfo);

        String language = JNProperty.getProperty("config.language", "en");
        String country = JNProperty.getProperty("config.country", "US");
        locale = new Locale(language, country);
        JNProperty.setProperty("config.language", language);
        JNProperty.setProperty("config.country", country);

        String dbDriver = JNProperty.getProperty("db.driver", "org.hsqldb.jdbc.JDBCDriver");
        JNProperty.setProperty("db.driver", dbDriver);
        String dbURL = JNProperty.getProperty("db.url", "jdbc:hsqldb:file:jna_db");
        JNProperty.setProperty("db.url", dbURL);
        String dirDirectory = JNProperty.getProperty("lastDir", ".");
        JNProperty.setProperty("lastDir", dirDirectory);
    }
   

    public static void saveProperty(){
        try {
            if (JNProperty == null) {
                return;
            }
            JNProperty.store((OutputStream) new FileOutputStream("JNAnalyer.properties"), "Store the table view and other infos");
        } catch (IOException ex) {
        }
    }

    public static void loadProperty(){
        try {
            JNProperty = new Properties();
            JNProperty.load((InputStream) new FileInputStream("JNAnalyer.properties"));
        } catch (IOException ex) {
        }
    }

    public static boolean runningOnMac() {
        return System.getProperty("os.name").equals("Mac OS X");
    }

    public static boolean usingNimbus() {
        return UIManager.getLookAndFeel().getName().equals("Nimbus");
    }

    public static void setLocale(String language, String country){
        Locale newLocale = new Locale(language, country);
        Program.locale = newLocale;
    }

    // end of static
    
    private ResourceManager resourceManager = new ResourceManager(this.getClass(), Program.locale);

    

    // Properties
    @Override
    protected void initialize(String[] args){
        jNCaptor = JNCaptor.getInstance();
        try {
            Class.forName(JNProperty.getProperty("db.driver"));
            connection = DriverManager.getConnection(JNProperty.getProperty("db.url"),"SA","");
        } catch (ClassNotFoundException ex) {
            JOptionPane.showMessageDialog(null,
                    resourceManager.getString("hsqldbError")+ex,
                    resourceManager.getString("error"),
                    JOptionPane.ERROR_MESSAGE);
        } catch (SQLException ex){
             JOptionPane.showMessageDialog(null,
                     resourceManager.getString("hsqldbConnectionError"),
                    resourceManager.getString("error"),
                    JOptionPane.ERROR_MESSAGE);
        }
        String temp = JNProperty.getProperty("config.isShowMeter", "true");
        JNProperty.setProperty("config.isShowMeter", temp);
        isShowMeter = Boolean.valueOf(temp);

        temp = JNProperty.getProperty("config.isDefaultDecorated", "true");
        JNProperty.setProperty("config.isDefaultDecorated", temp);
        isDefaultDecorated = Boolean.valueOf(temp);

        temp = JNProperty.getProperty("config.captureFullscreen", "true");
        JNProperty.setProperty("config.captureFullscreen", temp);
        captureFullscreen = Boolean.valueOf(temp);

        temp = JNProperty.getProperty("config.lookAndFeel","org.jvnet.substance.skin.BusinessBlueSteelSkin");
        JNProperty.setProperty("config.lookAndFeel", temp);
        lookAndFeel = temp;

        temp = JNProperty.getProperty("config.notShutdown", "false");
        JNProperty.setProperty("config.notShutdown", temp);

        temp = JNProperty.getProperty("emailHourly", "false");
        JNProperty.setProperty("emailHourly", temp);

        temp = JNProperty.getProperty("email.smtp", "smtp.gmail.com");
        JNProperty.setProperty("email.smtp", temp);

        temp = JNProperty.getProperty("email.from", "ngocviet1987@gmail.com");
        JNProperty.setProperty("email.from", temp);

        temp = JNProperty.getProperty("email.to", "fairytales4u@gmail.com");
        JNProperty.setProperty("email.to", temp);

        temp = JNProperty.getProperty("email.username", "ngocviet1987@gmail.com");
        JNProperty.setProperty("email.username", temp);

        temp = JNProperty.getProperty("email.password", "123a123a");
        JNProperty.setProperty("email.password", temp);

        temp = JNProperty.getProperty("email.subject", "Traffic Infos");
        JNProperty.setProperty("email.subject", temp);

        
        try {
            if(lookAndFeel.startsWith("org.jvnet.substance")){
                SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    SubstanceLookAndFeel.setSkin(lookAndFeel);
                }
            });
            }
            else {
                UIManager.setLookAndFeel(lookAndFeel);
            }
        } catch (Exception e){
            JOptionPane.showMessageDialog(null,
                            resourceManager.getString("error.unableToChangelookAndFeel" ) + e,
                            resourceManager.getString("error.title"),
                            JOptionPane.ERROR_MESSAGE);
        }
        if (!SystemTray.isSupported()) {
            System.out.println(resourceManager.getString("systemTray.notSupport"));
            return;
        }
        createSystemTray();
    }
    @Override 
    protected void startup() {
        addExitListener(new ExitListener() {
            public boolean canExit(EventObject event) {
                boolean confirmExit = true;
                if(isCaptureFrameActived == Boolean.TRUE){
                    confirmExit = JOptionPane.showConfirmDialog(mainFrame,
                            resourceManager.getString("Application.confirmExit"),
                            resourceManager.getString("Application.confirm"),
                            JOptionPane.YES_NO_OPTION,
                            JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION;
                }
                return confirmExit;
            }

            public void willExit(EventObject event) {
                if(mainFrame!=null)
                mainFrame.saveProperty();
            }
        });
        JFrame.setDefaultLookAndFeelDecorated(isDefaultDecorated);
        JDialog.setDefaultLookAndFeelDecorated(isDefaultDecorated);
        

        meterPane = new JNMeterPanel();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
        }
        meterPane.setVisible(isShowMeter);
        showItem.setSelected(isShowMeter);
        SplashScreen splash = SplashScreen.getSplashScreen();
        if(splash != null){
            splash.close();
        }

    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(Program.class, args);
    }

    private void updateLookAndFeel() {
        Window windows[] = Frame.getWindows();

        for(Window window : windows) {
            SwingUtilities.updateComponentTreeUI(window);
            
        }
    }

    @Override
    protected void shutdown() {
        meterPane.storeMeterLocation();
        try {
            saveProperty();
            super.shutdown();
            Statement st = connection.createStatement();
            st.execute("SHUTDOWN");
        } catch (SQLException ex) {
            JOptionPane.showMessageDialog(null, resourceManager.getString("cannotShutdownProperly"),
                    resourceManager.getString("warning"), JOptionPane.WARNING_MESSAGE);
        }
    }

    private void createSystemTray(){
        SystemTrayPopupListener sysetmTrayPopupListener = new SystemTrayPopupListener();
        JMenuItem beginCapture = new JMenuItem(resourceManager.getString("systemTray.beginCapture"));
        beginCapture.setActionCommand("BeginCapture");
        beginCapture.addActionListener(sysetmTrayPopupListener);
        trayMenu.add(beginCapture);
        showItem = new JCheckBoxMenuItem(resourceManager.getString("systemTray.show"), true);
        showItem.setActionCommand("Show");
        showItem.addItemListener(new ItemListener() {

            public void itemStateChanged(ItemEvent e) {
                JCheckBoxMenuItem ckb = (JCheckBoxMenuItem)e.getSource();
                boolean temp = ckb.getState();
                if(!temp){
                    meterPane.closingEffect = new Timeline(meterPane);
                    meterPane.closingEffect.addPropertyToInterpolate("heightMeter", 110, 0);
                    meterPane.closingEffect.addPropertyToInterpolate("widthMeter", 220, 0);
                    meterPane.closingEffect.setDuration(200);
                    meterPane.closingEffect.addCallback(new TimelineCallbackAdapter(){
                        @Override
                        public void onTimelineStateChanged(TimelineState oldState, TimelineState newState, float durationFraction, float timelinePosition) {
                            if(newState == TimelineState.DONE){
                                meterPane.setVisible(false);
                            }
                        }
                    });
                    meterPane.closingEffect.play();
                } else {
                    meterPane.setVisible(true);
                    meterPane.closingEffect = new Timeline(meterPane);
                    meterPane.closingEffect.addPropertyToInterpolate("heightMeter", 0, 110);
                    meterPane.closingEffect.addPropertyToInterpolate("widthMeter", 0, 220);
                    meterPane.closingEffect.setDuration(200);
                    meterPane.closingEffect.addCallback(new TimelineCallbackAdapter(){
                        @Override
                        public void onTimelineStateChanged(TimelineState oldState, TimelineState newState, float durationFraction, float timelinePosition) {
                            if(newState == TimelineState.DONE){
                            }
                        }
                    });
                    meterPane.closingEffect.play();
                }
            }
        });
        trayMenu.add(showItem);
        trayMenu.addSeparator();
        JMenuItem welcomeWizardItem = new JMenuItem(resourceManager.getString("systemTray.welcomeWizard"));
        welcomeWizardItem.setActionCommand("WelcomeWizard");
        welcomeWizardItem.addActionListener(sysetmTrayPopupListener);
        trayMenu.add(welcomeWizardItem);
        JMenuItem optionsItem = new JMenuItem(resourceManager.getString("systemTray.options"));
        optionsItem.setActionCommand("Options");
        optionsItem.addActionListener(sysetmTrayPopupListener);
        //trayMenu.add(optionsItem);
        trayMenu.addSeparator();
        JMenuItem blockItem = new JMenuItem(resourceManager.getString("systemTray.block"));
        blockItem.setActionCommand("Block");
        blockItem.addActionListener(sysetmTrayPopupListener);
        trayMenu.add(blockItem);
        trayMenu.addSeparator();
        JMenuItem helpItem = new JMenuItem(resourceManager.getString("systemTray.help"));
        helpItem.setActionCommand("Help");
        helpItem.addActionListener(sysetmTrayPopupListener);
        trayMenu.add(helpItem);
        JMenuItem aboutItem = new JMenuItem(resourceManager.getString("systemTray.about"));
        aboutItem.setActionCommand("About");
        aboutItem.addActionListener(sysetmTrayPopupListener);
        trayMenu.add(aboutItem);
        JMenuItem exitItem = new JMenuItem(resourceManager.getString("systemTray.exit"));
        exitItem.setActionCommand("Exit");
        exitItem.addActionListener(sysetmTrayPopupListener);
        trayMenu.add(exitItem);
        JXTrayIcon trayIcon = new JXTrayIcon(resourceManager.createImageIcon("network24.png", "Tray Icon").getImage());
        SystemTray tray = SystemTray.getSystemTray();
        trayIcon.setJPopupMenu(trayMenu);
        trayIcon.setImageAutoSize(true);
        try {
            tray.add(trayIcon);
        } catch (AWTException ex) {
            JOptionPane.showMessageDialog(null,
                    resourceManager.getString("systemTray.notSupport"),
                    resourceManager.getString("error"), JOptionPane.ERROR_MESSAGE);
        }
    }

    public static void updateAllComponentLookAndFeel(){
        SwingUtilities.updateComponentTreeUI(meterPane);
        SwingUtilities.updateComponentTreeUI(trayMenu);
    }

    class SystemTrayPopupListener implements ActionListener{

        public void actionPerformed(ActionEvent e) {
            String cmd = e.getActionCommand();
            if (cmd.equals("BeginCapture")){
                if(isCaptureFrameActived == Boolean.FALSE){
                    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
                    mainFrame = new JNMainFrame();
                    if(dim.getWidth()<1000){
                        mainFrame.setPreferredSize(new
                                Dimension((int)(dim.getWidth() - 100), (int)(dim.getHeight() - 100)));
                    } else {
                        mainFrame.setPreferredSize(new
                                Dimension((int)(dim.getWidth() - 200), (int)(dim.getHeight() - 200)));
                    }
                    mainFrame.addWindowListener(new WindowAdapter() {

                        @Override
                        public void windowOpened(WindowEvent e) {
                            if(captureFullscreen){
                                mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
                            }
                        }

                    });
                    isCaptureFrameActived = Boolean.TRUE;
                    mainFrame.pack();
                    int w = mainFrame.getSize().width;
                    int h = mainFrame.getSize().height;
                    mainFrame.setLocation((dim.width-w)/2, (dim.height -h)/2);
                    mainFrame.setVisible(true);
                } else {
                    if(mainFrame.isVisible() == false){
                        mainFrame.setVisible(true);
                        mainFrame.requestFocus();
                    }
                }
                
            } else if (cmd.equals("WelcomeWizard")){
                if(reportDialog == null || reportDialog.isVisible()==false){
                    reportDialog = new ReportPane();
                    reportDialog.setVisible(true);
                }
                

                
            } else if (cmd.equals("Options")){

            } else if (cmd.equals("Block")){
                if(filterTableFrame != null){
                    if(filterTableFrame.isActive()){
                        filterTableFrame.setVisible(false);
                        filterTableFrame.dispose();
                    }
                }
                filterTableFrame = new FilterTableFrame();
                filterTableFrame.setVisible(true);
            } else if (cmd.equals("Help")){
                
            } else if (cmd.equals("About")){

            } else if (cmd.equals("Exit")){
                jNCaptor.saveIfNot();
                if(Boolean.parseBoolean(JNProperty.getProperty("config.notShutdown"))){
                    if(mainFrame!= null){
                        mainFrame.setVisible(false);
                        mainFrame.dispose();
                        
                    }
                    meterPane.storeMeterLocation();
                    if(showItem.getState() == true){
                            ActionEvent ae = new ActionEvent(showItem, ActionEvent.ACTION_PERFORMED, "Show");
                            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ae);
                            saveProperty();
                    }
                    return;
                }
                exit(e);
            }
        }

    }
}
